#ifndef __CSBBIND_H_
#define __CSBBIND_H_

/**
 * Desc: 用来提供C++的绑定功能
 * Auth: 张宇飞
 * Date: 2015-02-23    
 */

#include "csnode.h"
#include "utils.h"
#include "coord.h"
#include <list>
#include <map>
#include <set>
#include <string>
#include <vector>

/*********************| 宏定义 |*********************/
#define US_NS_CSB	using namespace CSB
#define NS_CSB_BEGIN	namespace CSB {
#define NS_CSB_END	}

NS_CSB_BEGIN

class BindHelperProto;
/**
 * @brief BindProto 绑定协议
 */
class CSB_DLL BindProto
{
public:
	enum {
		RUNNING           = 0x1,// 运行绑定节点
		UPDATE_PASSIVE    = 0x2,// 接受被绑定的node的改变
		RM_BULLET_ATONCE  = 0x4,// 立刻删除活着的子弹,并禁止子弹的生成
		OBJ_COLOR_BLEND   = 0x8, // obj can set color and alpha
		BULLET_COLOR_BLEND= 0x10, // bullet can set color and alpha
		FINAL		  = 0x20,// 立刻删除所有的子弹,取消子弹节点的连接
		FIRST_SETUPED	  = 0x40 // 第一次加载
	};

	struct bindele_t{
		int		flag;		// 控制位
		char		objdatana[16];	// 绑定的索引
		csnode_t*	pcs;		
//		void*		udata;		// 用户自定义数据
		pos_t		posOffset;	// 位置修正
		int16_t		angleOffset;	// 角度修正
		int16_t		live;		// 生死
	};

	/*  绑定用的结构 */
	struct bind_t {
 		std::string 		fname;
		BindProto*		proto;
		std::list<bindele_t*>	eleList;
	};

	struct Bind2ELE_t {
		BindProto::bind_t*	b;
		BindProto::bindele_t*	e;
	};

public:
	BindProto(BindHelperProto* h, void* pobj);
	virtual ~BindProto();

public:
	static bind_t*		newBind(BindProto* p = NULL, const char* fname = NULL);
	static bindele_t*	getEleN(bind_t* pb, size_t n);

protected:
	static void 		liveJudge(BindProto::bindele_t* pb,  const size_t j1);
	static int 		remove_bu_node_fun(void** datare, void* flag);
protected:
	/* 更新发射器的绘制信息 */
	virtual void		updateEleBase(bindele_t*p) = 0;
	/* 更新子弹的绘制信息 */
	virtual void 		updateBulletWithEle(const elebase_t& ele, void* pb) = 0;
	virtual void		bindObjRelease() = 0;
public:
	/* 解除绑定 */
	virtual void		unbindMe(bind_t*, const int);
	virtual void		clearBulletsOnce(bind_t*);
	/* 开始发射 */
	virtual void		onBegin(const char*, bindele_t*);
	/* 结束发射 */
	virtual void		onEnd(const char*, bindele_t*);
	/* 发射器刷新 */
	virtual void		onObjUpdate(const char*, bindele_t*);
	/* 子弹出生 */
	virtual void*		onBulletBorn(const char*fname, bullet_t* p, bindele_t* pb);
	/* 子弹死亡 */
	virtual void		onBulletDead(const char*, bullet_t*, bindele_t*);
	/* 子弹刷新 */
	virtual int		onBulletUpdate(const char*, bullet_t*, bindele_t*);
	/* 自狙击 */
	virtual void		onAutoMachine(const char*, bindele_t*, pos_t*);

protected:
	BindHelperProto*	_helper;
	void*			_bindObj;
};

/**
 * @brief BindHelperProto 这是用户层面要去实现的东西
 */
class CSB_DLL BindHelperProto
{
public:
	/* 用来更新子弹状态的 */
	struct BulletStateCheck_t {
		void*			buObj;
		int32_t			bID;
		const char*		fname;
		const char*		emName;
		const elebase_t*	pele;
	};

	/* 用来回收子弹的　*/
	struct BuRecyleHelper_t {
		BindHelperProto*	helper;
		const char*		fname;
		const char*		objdataName;
	};


public:
	/* 获取一个用于显示的子弹对象 */
	virtual void*		emitBullet(int buID, const char* fname, const char* objdatana) = 0;

	/* 用来回收一个子弹对象 */
	virtual void		recycleBullet(void* bu, int buID, const char* fname, const char* objdatana) = 0;

	/* 更新子弹的状态 */
	virtual int		bulletStateCheck(BulletStateCheck_t& bs) = 0;

	/* 自动狙击 */
	virtual void		autoMachine(pos_t* out) = 0;

	/* csobj死亡的时候的一个回调 */
	virtual void		objEndCB(const BindProto::bindele_t* pe) {}

};

/**
 * @brief CSBBindMan 绑定的管理类
 */
#define OBJ_DATA_MAP_TYPE std::string, csobjdata_t*
class CSB_DLL CSBBindMan
{
public:
	struct LoadFilesInfo {
		std::string	fname;
		size_t		objn;
	};
public:
	CSBBindMan ();
	virtual ~CSBBindMan ();

	/* 初始化，传入设计的视口的尺寸 */
	static bool 		init(float designW, float designH);
	static bool 		end();

	/* 获得数据对象的索引名 */
	static void 		CSMakeObjDataName(const int etype, const uint32_t NO, char* out, const size_t outlen);
protected:
	static void 		csbfilename_head(const char* src, char* out);
	static int 		addobjdata_func(void** datare, void* flag);

protected:
	/* 加载文件数据 */
	virtual unsigned char* loadCSBFileData(const char* path) = 0;
	/* 执行一次更新运算 */
	virtual void		updateOnce();

public:
	/* 加载文件[列表]xxx.csb */
	bool			loadfile(const char* path);
	bool			loadfile(const std::vector<const char*>& filesVec);

	/* 释放文件[列表], fname 是xxx.csb中的xxx */
	void			unloadobjdata(const char* fname, const char* objdatana);
	void			unloadfile(const char* fname);
	void			unloadAll();
	
	/* 获取加载的文件列表 */
	void			loadFilesInfo(std::vector<LoadFilesInfo>& v);

	/* 绑定,解绑 */
	bool			bind(BindProto::bind_t* pb);
	void			unbind(BindProto::bind_t* pb, bool rmBu, bool dofinal = false);
	void			unbindAll(bool rmBu, bool dofinal = false);

	/* 运行 */
	void 			run(BindProto::bind_t* p, bool r, bool emitNow = true);
	void 			run(BindProto::bind_t* p, size_t n, bool r, bool emitNow = true);

	/* 立刻咔咔掉所有的bullet */
	void			kakaAllBulletsOnce();
protected:
	/* 绑定用的map */
	std::map<std::string, std::map<OBJ_DATA_MAP_TYPE>* > _objsMap;
	/* 绑定了的节点, bool是控制是否刷新的 */
	std::set<BindProto::bind_t*>	_bindSet;
protected:
	static bool		_inited;
};

NS_CSB_END

#endif /* end of include guard: __CSBBIND_H_ */
